﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

using TFSClient = Microsoft.TeamFoundation.WorkItemTracking.Client;

using LeMigue.Scrum.TfsScrumV1.Utils;
using LeMigue.Scrum.Iterface.Service;
using LeMigue.Scrum.Iterface.Model;
using LeMigue.Scrum.Iterface.Enum;

namespace LeMigue.Scrum.TfsScrumV1.Service
{
    public class TaskService : AbstractTfsService, ITaskService
    {


        private WorkItemFields[] QuerySelect = new WorkItemFields[] { };


        public IList<Task> List(int idParent)
        {
            TfsQueryLinkItem query = new TfsQueryLinkItem(QuerySelect, TfsQueryLinkItem.Mode.MustContain, idParent);

            query.AppendWhere("AND").AppendWhere(WorkItemFields.LinkType, "=", WorkItemLinkType.Child.ToString())
                 .AppendWhere("AND").AppendWhere(WorkItemFields.TargetWorkItemType, "=", WorkItemType.Task.ToString());

            return List(GetItensByLinks(query), false);
        }

        public IList<Task> List(Sprint sprint)
        {
            TfsQueryItem query = new TfsQueryItem(QuerySelect);

            query.AppendWhere(WorkItemFields.IterationId, "=", sprint.Iteration.Id)
                 .AppendWhere(" AND ").AppendWhere(WorkItemFields.WorkItemType, "=", WorkItemType.Task.ToString());


            return List(GetItens(query), true);
        }

        public IList<Task> List(ItemBacklog backlog)
        {
            return List(backlog.Id);
        }

        public IList<Task> List(Bug bug)
        {
            return List(bug.Id);
        }

        public IList<Task> List(Task task)
        {
            return List(task.Id);
        }

        private IList<Task> List(TFSClient.WorkItemCollection workItemCollection, bool checkChild)
        {
            IList<Task> tasks = new List<Task>();
            foreach (TFSClient.WorkItem item in workItemCollection)
            {
                if (!checkChild || (item.WorkItemLinks.Count == 0 || !item.WorkItemLinks.ContainParent(WorkItemLinkType.Parent.ToString())))
                {
                    Task task = item.ConvertToScrumItem<Task>(CreateTask);
                    tasks.Add(task);
                }
            }

            return tasks;
        }
        private IList<Task> List(IList<TFSClient.WorkItem> listWorkItem, bool checkChild)
        {
            IList<Task> tasks = new List<Task>();
            foreach (TFSClient.WorkItem item in listWorkItem)
            {
                if (!checkChild || (item.WorkItemLinks.Count == 0 || !item.WorkItemLinks.ContainParent(WorkItemLinkType.Parent.ToString())))
                {
                    Task task = item.ConvertToScrumItem<Task>(CreateTask);
                    tasks.Add(task);
                }
            }

            return tasks;
        }

        public Task Load(int id)
        {
            return GetItem(id).ConvertToScrumItem<Task>(CreateTask);
        }

        public Task Save(Task item){

            if (item.Id <= 0)
                Save(item.ConvertToWorkItem<Task>(GetNewItem(item), SaveTask));
            else
                Save(item.ConvertToWorkItem<Task>(GetItem(item.Id), SaveTask));

            return item;
        }

        //TODO: Melhorar bem esta parte
        protected TFSClient.WorkItem GetNewItem(Task item)
        {
            TFSClient.WorkItemStore workItemStore = GetService<TFSClient.WorkItemStore>();

            TFSClient.WorkItemType wit = workItemStore.Projects[item.Team.Title].WorkItemTypes[WorkItemType.Task.ToString()];

            TFSClient.WorkItem w = new TFSClient.WorkItem(wit);

            if (item.Parent > 0)
            {
                w.Links.Add(new TFSClient.RelatedLink(workItemStore.WorkItemLinkTypes.LinkTypeEnds[WorkItemLinkType.Parent.ToString()], item.Parent));
            }
            return w;
        }

        protected Task CreateTask(TFSClient.WorkItem w, Task item)
        {

            item.State = WorkItemState.StateByWorkItemState(w.State).ScrumState;

            item.AssingTo = w["System.AssignedTo"] == null ? null : (User)new MemberService().Load<User>(w.Project, (string)w["System.AssignedTo"]);
            item.RemainingWork = w[WorkItemFields.RemainingWork.ToString()] == null ? (double?)null : (double?)w[WorkItemFields.RemainingWork.ToString()];

            item.SetTasks(new System.Lazy<IList<Task>>(() => List(item)));

            TFSClient.Node no = w.Project.IterationRootNodes.GetNode(w.IterationId);
            if (no != null)
            {
                item.Iteration = new Iteration(no.Id, no.Name);
            }
            //TODO: melhorar bem esta parte
            item.Team = new TeamProjectService().Load(w.Project.Id);

            return item;
        }
        protected TFSClient.WorkItem SaveTask(Task item, TFSClient.WorkItem w)
        {
            w.Title = item.Title;
            w.Description = item.Description;
            w[WorkItemFields.RemainingWork.ToString()] = item.RemainingWork;
            w.IterationId = item.Iteration.Id;

            return w;
        } 
        
    }
}
